#ifndef skyPtr_h__
#define skyPtr_h__

#include "./skyType.h"
#include "./skyRtti.h"


namespace Sky
{

class Object;
//////////////////////////////////////////////////////////////////////////
class PtrWrapper
{
protected:
	Object* ptr;
public:
	PtrWrapper():ptr(vNull){}
	~PtrWrapper();
public:
	Object* leakPtr(){return ptr;}

};

template <typename CLS>
class AutoPtr
{
public:
	typedef CLS type;
	CLS* ptr;
public:
	AutoPtr(){}
	AutoPtr(CLS * p){ptr = p;}
	~AutoPtr(){if(ptr)delete ptr;}
};
//////////////////////////////////////////////////////////////////////////
template <typename CLS>
class RefPtr : public PtrWrapper
{
public:
	typedef CLS type;
public:
	RefPtr(){}

	RefPtr(CLS* p)
	{
		if(p)p->incRef();
		if(ptr)ptr->decRef();
		ptr = p;
	}

	~RefPtr(){}

	RefPtr(RefPtr& r)
	{
		if(r)r->incRef();
		if(ptr)ptr->decRef();
		ptr = r;
	}

	template <typename CLS2>
	RefPtr( RefPtr<CLS2>& rref )
	{
		if(rref)rref->incRef();
		if(ptr)ptr->decRef();
		ptr = rref.leakPtr();
	}

	void operator = (RefPtr& rref);
	void operator = (CLS* p)
	{
		if(p)p->incRef();
		if(ptr)ptr->decRef();
		ptr = p;
	}
	//void operator = (CLS& p)
	//{
	//	if(p == vNull)
	//	{
	//		p = new (CLS(p));
	//	}
	//}
	CLS* operator ->(){return leakPtr();}

	CLS* leakPtr(){return (CLS*)PtrWrapper::leakPtr();}

	operator CLS* () { return leakPtr(); }

};
template <typename CLS>
void RefPtr<CLS>::operator=( RefPtr& rref )
{
	if(rref)rref->incRef();
	if(ptr)ptr->decRef();
	ptr = rref.leakPtr();
}
}
#endif // skyPtr_h__